// @Author miaoqing
// @Date 2024/02/23 16:21:00
// @Desc
package logic

import (
	"core/command"
	"core/common"
	"core/component/logger"
	"core/network"
	"sync"
	"time"
)

var (
	gcOnce           sync.Once
	gatewayClientMgr *GatewayClientMgr
)

// GatewayClientMgr gateway server client manager
type GatewayClientMgr struct {
	clients         *sync.Map
	lastDiscoveryTM time.Time
}

func gatewayClientMgrGetMe() *GatewayClientMgr {
	gcOnce.Do(func() {
		gatewayClientMgr = &GatewayClientMgr{
			clients: &sync.Map{},
		}
	})
	return gatewayClientMgr
}

func (mgr *GatewayClientMgr) sendRowMsgToGatewayClient(srvID string, userID uint64, data []byte) bool {
	client, ok := mgr.clients.Load(srvID)
	if !ok {
		logger.Warningf("can not found gateway client connection srvID:%v userID:%v", srvID, userID)
		return false
	}
	return client.(*GatewayClient).sendRowMsgToClient(userID, data)
}

func (mgr *GatewayClientMgr) addGatewayClient(srvID string, client *GatewayClient) {
	c, ok := mgr.clients.Load(srvID)
	if ok {
		gClient := c.(*GatewayClient)
		logger.Warningf("网关连接已存在 ID:%v Addr:%v", gClient.serverID, gClient.serverAddr)
		return
	}
	client.registerMsgs()
	mgr.clients.Store(srvID, client)
	logger.Infof("添加网关连接 srvID:%v Addr:%v", client.serverID, client.serverAddr)
}

// 配置online服处理的消息ID 发送给gateway 由gateway统一转发到online服
func (gc *GatewayClient) registerMsgs() {
	for cmd := command.Command_OnlineStart_Online; cmd < command.Command_OnlineEnd_Online; cmd++ {
		_, ok := command.Command_name[int32(cmd)]
		if !ok {
			continue
		}
		gc.msgID = append(gc.msgID, uint32(cmd))
	}
}

func (mgr *GatewayClientMgr) checkConnect() {
	mgr.clients.Range(func(key, value any) bool {
		client := value.(*GatewayClient)
		client.checkConnect(client.serverAddr)
		return true
	})
}

func (mgr *GatewayClientMgr) discoveryGatewaySrv() {
	resp := &common.GetAllServerInfoResp{}
	err := common.SendCenterHttpRequest(nil, resp, "GET", "/getAllGatewayServer")
	if err != nil {
		return
	}
	mgr.clearInvalidGatewayClient(resp.SInfos)
	for _, srv := range resp.SInfos {
		if _, ok := mgr.clients.Load(srv.ServerID); ok {
			continue
		}
		client := &GatewayClient{
			tcpClient:  network.NewTcpClient(16*1024, 16*1024),
			serverID:   srv.ServerID,
			serverAddr: srv.Addr,
		}
		client.tcpClient.OnCloseCallBack = client.OnCloseCallBack
		mgr.addGatewayClient(srv.ServerID, client)
	}
}

func (mgr *GatewayClientMgr) sendMsgToGatewayClient(srvID string, userID uint64, cmd command.Command, msg interface{}) bool {
	client, ok := mgr.clients.Load(srvID)
	if !ok {
		logger.Warningf("[连接] 找不到网关连接 serverID:%v userID:%v", srvID, userID)
		return false
	}
	return client.(*GatewayClient).sendMsgToClient(userID, cmd, msg)
}

func (mgr *GatewayClientMgr) clearInvalidGatewayClient(services []*common.ServerInfo) {
	mgr.clients.Range(func(k, v interface{}) bool {
		client, ok := v.(*GatewayClient)
		if ok {
			find := false
			for _, svcEntry := range services {
				//info := function.GetPerformanceData(svcEntry.Service.Tags[0])
				//if client.ZoneId == info.Zid && client.serverID == svcEntry.Service.ID {
				if client.serverID == svcEntry.ServerID {
					find = true
				}
			}
			if !find {
				mgr.clients.Delete(client.serverID)
			}
		}
		return true
	})
}

func (mgr *GatewayClientMgr) sendMsgToGateway(srvID string, cmd command.Command, msg interface{}) bool {
	client, ok := mgr.clients.Load(srvID)
	if !ok {
		logger.Warningf("[连接] 找不到网关连接 serverID:%v", srvID)
		return false
	}
	return client.(*GatewayClient).sendMsg(cmd, msg)
}

func (mgr *GatewayClientMgr) centerClose() {
	mgr.clients = &sync.Map{}
}
